MySQL クラッシュリカバリ
クラッシュとは
そもそもクラッシュとはなんやねんと...
「MySQLサーバーが壊れて動かなくなる」ってことをクラッシュと言う。
データベースは正常な状態なんだが、どうもサーバープロセスが壊れる的な感じ。
このクラッシュは様々な要因で起きうる
データベースが載ってるマシン障害や電源ぶつ切り
メモリー、ディスク、CPU、ネットワーク障害
MySQLサービスの強制シャットダウン
CPU負荷が高すぎてクラッシュ
ディスクI/O待ち時間が長すぎてクラッシュ
etc
クラッシュリカバリとは
クラッシュ後にMySQLが再起動した時、データが整ってない状態を、整合性の取れた状態にする処理・機能のこと。
クラッシュが起きるということは、DBプロセスが途中でぶつ切りされるわけなので、DBMSとして綺麗に動くデータの持ち方じゃないまま落ちてる可能性が非常に高い。
そのような汚い状態を綺麗にするのがクラッシュリカバリ。
クラッシュリカバリの流れ
1. InnoDB Redo ログの適用(ロールフォワード)
2. 未完了トランザクションのロールバック
3. 挿入バッファーのマージ
4. パージ
1. InnoDB Redo ログの適用(ロールフォワード)
InnoDBのデータ書き込みの仕組みでは、COMMITした内容をInnoDB Redo Logファイルにはすぐに反映するが、データ本体であるtablespaceにはすぐに反映しないという特徴がある。
本体データはメモリに残った状態のまま、定期的にディスクに反映されるようになっている。
このメモリに残った状態のまま、クラッシュが発生してしまうと厄介になる。
なぜなら、COMMITしたはずのデータがtablespaceのディスクに反映されないまま消えてしまうから。
ただ、それを心配する必要はなく、それへの対策としてInnoDB Redo Logが存在する。
このログファイルは永続化されており、クラッシュしても消えない。
なので、クラッシュリカバリは、このRedo Logを元にCOMMITしたのに永続化されてない本体データをtablespaceに反映していく。
もっと詳しく言うと、Redo Logの中にあるチェックポイントがついてないログイベントを全てtablespaceに反映していく。
2. 未完了トランザクションのロールバック
逆にCOMMITされてないトランザクション内容がtablespaceに反映されてしまうこともある。
InnoDBでは、バッファプールにおけるダーティページの割合がinnodb_max_dirty_pageを超えた場合、勝手にtablespaceにデータを反映する仕様がある。
この状態でクラッシュが起きたとしよう。
そうなると今度は「1.」とは逆に、ディスクに残っていてはいけない形でデータ更新が残ってしまうことになる。
つまり、トランザクション完了してないデータがディスクに残る。
この状態はいけない。汚い状態である。
この不整合を正すために、クラッシュリカバリはUndo Logを利用する。
Undo Logは、ロールバック後に元のデータに戻すためにInnoDBが保持してるデータである。
このUndo Logを利用して、トランザクション未完了のデータを元のデータに戻している。
その他ポイント
innodb_log_file_sizeでInnoDB Redo Logファイルのサイズを大きくすると、クラッシュリカバリ時にその分だけ時間がかかるようになる。
重要.icon「バイナリログが有効」x「2フェーズ(XA)トランザクションが有効」の場合、クラッシュリカバリ時にバイナリログの整合性チェックも行われる。
必要に応じてロールバック及びロールフォワードがなされる。
参考